home *** CD-ROM | disk | FTP | other *** search
/ Isometric Game Programming with DirectX 7.0 / Isometric Game Programming.iso / directx / dxf / samples / multimedia / direct3d / dxtex / dxtexdoc.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-22  |  57.0 KB  |  1,929 lines

  1. // dxtexDoc.cpp : implementation of the CDxtexDoc class
  2. //
  3.  
  4. #include "stdafx.h"
  5. #include "dxtex.h"
  6. #include "dxtexDoc.h"
  7. #include "dialogs.h"
  8. #include "dds.h"
  9.  
  10. #ifdef _DEBUG
  11. #define new DEBUG_NEW
  12. #undef THIS_FILE
  13. static char THIS_FILE[] = __FILE__;
  14. #endif
  15.  
  16. /////////////////////////////////////////////////////////////////////////////
  17. // CDxtexDoc
  18.  
  19. IMPLEMENT_DYNCREATE(CDxtexDoc, CDocument)
  20.  
  21. BEGIN_MESSAGE_MAP(CDxtexDoc, CDocument)
  22.     //{{AFX_MSG_MAP(CDxtexDoc)
  23.     ON_COMMAND(ID_FILE_OPENALPHA, OnFileOpenAlpha)
  24.     ON_COMMAND(ID_FORMAT_GENERATEMIPMAPS, OnGenerateMipMaps)
  25.     ON_COMMAND(ID_FORMAT_CHANGESURFACEFMT, OnFormatChangeSurfaceFmt)
  26.     ON_COMMAND(ID_FORMAT_CHANGECUBEMAPFACES, OnFormatChangeCubeMapFaces)
  27.     ON_COMMAND(ID_FORMAT_MAKEINTOVOLUMEMAP, OnFormatMakeIntoVolumeMap)
  28.     ON_UPDATE_COMMAND_UI(ID_FILE_OPENALPHA, OnUpdateFileOpenAlpha)
  29.     ON_UPDATE_COMMAND_UI(ID_FORMAT_GENERATEMIPMAPS, OnUpdateFormatGenerateMipmaps)
  30.     ON_UPDATE_COMMAND_UI(ID_FORMAT_CHANGECUBEMAPFACES, OnUpdateFormatChangeCubeMapFaces)
  31.     ON_UPDATE_COMMAND_UI(ID_FORMAT_MAKEINTOVOLUMEMAP, OnUpdateFormatMakeIntoVolumeMap)
  32.     //}}AFX_MSG_MAP
  33. END_MESSAGE_MAP()
  34.  
  35. /////////////////////////////////////////////////////////////////////////////
  36. // CDxtexDoc diagnostics
  37.  
  38. #ifdef _DEBUG
  39. void CDxtexDoc::AssertValid() const
  40. {
  41.     CDocument::AssertValid();
  42. }
  43.  
  44. void CDxtexDoc::Dump(CDumpContext& dc) const
  45. {
  46.     CDocument::Dump(dc);
  47. }
  48. #endif //_DEBUG
  49.  
  50. /////////////////////////////////////////////////////////////////////////////
  51. // CDxtexDoc construction/destruction
  52.  
  53. CDxtexDoc::CDxtexDoc()
  54. {
  55.     m_ptexOrig = NULL;
  56.     m_ptexNew = NULL;
  57.     m_dwWidth = 0;
  58.     m_dwHeight = 0;
  59.     m_dwDepth = 0;
  60.     m_numMips = 0;
  61.     m_dwCubeMapFlags = 0;
  62.     m_bTitleModsChanged = FALSE;
  63. }
  64.  
  65.  
  66. CDxtexDoc::~CDxtexDoc()
  67. {
  68.     ReleasePpo(&m_ptexOrig);
  69.     ReleasePpo(&m_ptexNew);
  70. }
  71.  
  72.  
  73. BOOL CDxtexDoc::OnNewDocument()
  74. {
  75.     HRESULT hr;
  76.     LPDIRECT3DDEVICE8 pd3ddev = PDxtexApp()->Pd3ddev();
  77.  
  78.     if (!CDocument::OnNewDocument())
  79.         return FALSE;
  80.  
  81.     CNewTextureDlg dlg;
  82.  
  83.     if (IDCANCEL == dlg.DoModal())
  84.         return FALSE;
  85.  
  86.     m_dwWidth = dlg.m_dwWidth;
  87.     m_dwHeight = dlg.m_dwHeight;
  88.     m_numMips = dlg.m_numMips;
  89.  
  90.     if (dlg.m_iTexType == 0)
  91.     {
  92.         LPDIRECT3DTEXTURE8 pmiptex;
  93.         hr = pd3ddev->CreateTexture(m_dwWidth, m_dwHeight, m_numMips, 
  94.             0, dlg.m_fmt, D3DPOOL_MANAGED, &pmiptex);
  95.         if (FAILED(hr))
  96.         {
  97.             AfxMessageBox(ID_ERROR_CANTCREATETEXTURE);
  98.             return FALSE;
  99.         }
  100.         m_ptexOrig = pmiptex;
  101.  
  102.     }
  103.     else if (dlg.m_iTexType == 1)
  104.     {
  105.         // Cube Map
  106.         LPDIRECT3DCUBETEXTURE8 pcubetex;
  107.         m_dwCubeMapFlags = DDS_CUBEMAP_ALLFACES;
  108.         hr = pd3ddev->CreateCubeTexture(m_dwWidth, m_numMips, 
  109.             0, dlg.m_fmt, D3DPOOL_MANAGED, &pcubetex);
  110.         if (FAILED(hr))
  111.         {
  112.             AfxMessageBox(ID_ERROR_CANTCREATETEXTURE);
  113.             return FALSE;
  114.         }
  115.         m_ptexOrig = pcubetex;
  116.     }
  117.     else
  118.     {
  119.         LPDIRECT3DVOLUMETEXTURE8 pvoltex;
  120.         m_dwDepth = dlg.m_dwDepth;
  121.         hr = pd3ddev->CreateVolumeTexture(m_dwWidth, m_dwHeight, m_dwDepth, m_numMips, 
  122.             0, dlg.m_fmt, D3DPOOL_SYSTEMMEM, &pvoltex);
  123.         if (FAILED(hr))
  124.         {
  125.             AfxMessageBox(ID_ERROR_CANTCREATETEXTURE);
  126.             return FALSE;
  127.         }
  128.         m_ptexOrig = pvoltex;
  129.     }
  130.  
  131.     return TRUE;
  132. }
  133.  
  134.  
  135. /////////////////////////////////////////////////////////////////////////////
  136. // CDxtexDoc serialization
  137.  
  138. void CDxtexDoc::Serialize(CArchive& ar)
  139. {
  140.     HRESULT hr;
  141.     
  142.     if (ar.IsStoring())
  143.     {
  144.         LPDIRECT3DBASETEXTURE8 ptex;
  145.         ptex = (m_ptexNew == NULL ? m_ptexOrig : m_ptexNew);
  146.         SaveDDS(ptex, ar);
  147.     }
  148.     else
  149.     {
  150.         CFile* pFile = ar.GetFile();
  151.         CString str = pFile->GetFilePath();
  152.         TCHAR* pszExt = strrchr(str, '.');
  153.         if (lstrcmpi(pszExt, ".bmp") == 0 || lstrcmpi(pszExt, ".tga") == 0)
  154.         {
  155.             if (FAILED(hr = LoadBmp(str)))
  156.                 AfxThrowArchiveException(CArchiveException::generic);
  157.         }
  158.         else if (lstrcmpi(pszExt, ".dds") == 0)
  159.         {
  160.             ReleasePpo(&m_ptexOrig);
  161.             ReleasePpo(&m_ptexNew);
  162.             if (FAILED(hr = LoadDDS(&m_ptexOrig, ar)))
  163.                 AfxThrowArchiveException(CArchiveException::badIndex); // invalid file format
  164.         }
  165.         else
  166.         {
  167.             AfxThrowArchiveException(CArchiveException::badIndex); // invalid file format
  168.         }
  169.     }
  170. }
  171.  
  172.  
  173. HRESULT CDxtexDoc::SaveDDS(LPDIRECT3DBASETEXTURE8 ptex, CArchive& ar)
  174. {
  175.     HRESULT hr;
  176.     DDS_HEADER ddsh;
  177.     DWORD dwMagic;
  178.     D3DFORMAT fmt;
  179.     DWORD dwSize;
  180.     DWORD dwPitch = 0;
  181.     D3DLOCKED_RECT lr;
  182.     D3DLOCKED_BOX lb;
  183.     LPDIRECT3DTEXTURE8 pmiptex = NULL;
  184.     LPDIRECT3DCUBETEXTURE8 pcubetex = NULL;
  185.     LPDIRECT3DVOLUMETEXTURE8 pvoltex = NULL;
  186.  
  187.     if (IsVolumeMap())
  188.         pvoltex = (LPDIRECT3DVOLUMETEXTURE8)ptex;
  189.     else if (!IsCubeMap())
  190.         pmiptex = (LPDIRECT3DTEXTURE8)ptex;
  191.     else
  192.         pcubetex = (LPDIRECT3DCUBETEXTURE8)ptex;
  193.  
  194.     dwMagic = MAKEFOURCC('D','D','S',' ');
  195.     ar.Write(&dwMagic, sizeof(dwMagic));
  196.  
  197.     // Fill in the DDS header structure
  198.     ZeroMemory(&ddsh, sizeof(ddsh));
  199.     ddsh.dwSize = sizeof(ddsh);
  200.     ddsh.dwHeaderFlags = DDS_HEADER_FLAGS_TEXTURE;
  201.     ddsh.dwWidth = m_dwWidth;
  202.     ddsh.dwHeight = m_dwHeight;
  203.     ddsh.dwSurfaceFlags = DDS_SURFACE_FLAGS_TEXTURE;
  204.     if (m_numMips > 1)
  205.     {
  206.         ddsh.dwHeaderFlags |= DDS_HEADER_FLAGS_MIPMAP;
  207.         ddsh.dwSurfaceFlags |= DDS_SURFACE_FLAGS_MIPMAP;
  208.         ddsh.dwMipMapCount = m_numMips;
  209.     }
  210.     if (pvoltex != NULL)
  211.     {
  212.         ddsh.dwHeaderFlags |= DDS_HEADER_FLAGS_VOLUME;
  213.         // Note: "dwCubemapFlags" is mostly for cubemap flags,
  214.         // but in this case is also used to indicate a volume texture
  215.         ddsh.dwCubemapFlags |= DDS_FLAGS_VOLUME;
  216.         ddsh.dwDepth = m_dwDepth;
  217.     }
  218.     
  219.     // In DX7, you could (optionally) use and save a subset of 
  220.     // cubemap faces.  In DX8, you must use and save all faces of a cubemap.
  221.     if (IsCubeMap())
  222.     {
  223.         ddsh.dwSurfaceFlags |= DDS_SURFACE_FLAGS_CUBEMAP;
  224.         ddsh.dwCubemapFlags = DDS_CUBEMAP_ALLFACES;
  225.     }
  226.  
  227.     // Determine dwPitch and dwSize for the texture
  228.     if (pvoltex != NULL)
  229.     {
  230.         D3DVOLUME_DESC vd;
  231.         pvoltex->GetLevelDesc(0, &vd);
  232.         fmt = vd.Format;
  233.         dwSize = vd.Size;
  234.         if (SUCCEEDED(pvoltex->LockBox(0, &lb, NULL, D3DLOCK_READONLY)))
  235.         {
  236.             dwPitch = lb.RowPitch;
  237.             pvoltex->UnlockBox(0);
  238.         }
  239.     }
  240.     else if (pmiptex != NULL)
  241.     {
  242.         D3DSURFACE_DESC sd;
  243.         pmiptex->GetLevelDesc(0, &sd);
  244.         fmt = sd.Format;
  245.         dwSize = sd.Size;
  246.         if (SUCCEEDED(pmiptex->LockRect(0, &lr, NULL, D3DLOCK_READONLY)))
  247.         {
  248.             dwPitch = lr.Pitch;
  249.             pmiptex->UnlockRect(0);
  250.         }
  251.     }
  252.     else
  253.     {
  254.         D3DSURFACE_DESC sd;
  255.         pcubetex->GetLevelDesc(0, &sd);
  256.         fmt = sd.Format;
  257.         dwSize = sd.Size;
  258.         if (SUCCEEDED(pcubetex->LockRect(D3DCUBEMAP_FACE_POSITIVE_X, 0, 
  259.             &lr, NULL, D3DLOCK_READONLY)))
  260.         {
  261.             dwPitch = lr.Pitch;
  262.             pcubetex->UnlockRect(D3DCUBEMAP_FACE_POSITIVE_X, 0);
  263.         }
  264.     }
  265.  
  266.     // Note that although this code stores the pitch or linear size
  267.     // of the surface in the DDS file (for consistency with DX7), it
  268.     // is better to use the pitch or linear size of the surface
  269.     // created when loading the DDS file into a texture than to use
  270.     // the file values.  The pitch of a created surface, especially, 
  271.     // can be different from the pitch stored in the DDS file.
  272.     switch (fmt)
  273.     {
  274.     case D3DFMT_DXT1:
  275.         ddsh.ddspf = DDSPF_DXT1;
  276.         ddsh.dwHeaderFlags |= DDS_HEADER_FLAGS_LINEARSIZE;
  277.         ddsh.dwPitchOrLinearSize = dwSize;
  278.         break;
  279.     case D3DFMT_DXT2:
  280.         ddsh.ddspf = DDSPF_DXT2;
  281.         ddsh.dwHeaderFlags |= DDS_HEADER_FLAGS_LINEARSIZE;
  282.         ddsh.dwPitchOrLinearSize = dwSize;
  283.         break;
  284.     case D3DFMT_DXT3:
  285.         ddsh.ddspf = DDSPF_DXT3;
  286.         ddsh.dwHeaderFlags |= DDS_HEADER_FLAGS_LINEARSIZE;
  287.         ddsh.dwPitchOrLinearSize = dwSize;
  288.         break;
  289.     case D3DFMT_DXT4:
  290.         ddsh.ddspf = DDSPF_DXT4;
  291.         ddsh.dwHeaderFlags |= DDS_HEADER_FLAGS_LINEARSIZE;
  292.         ddsh.dwPitchOrLinearSize = dwSize;
  293.         break;
  294.     case D3DFMT_DXT5:
  295.         ddsh.ddspf = DDSPF_DXT5;
  296.         ddsh.dwHeaderFlags |= DDS_HEADER_FLAGS_LINEARSIZE;
  297.         ddsh.dwPitchOrLinearSize = dwSize;
  298.         break;
  299.     case D3DFMT_A8R8G8B8:
  300.         ddsh.ddspf = DDSPF_A8R8G8B8;
  301.         ddsh.dwHeaderFlags |= DDS_HEADER_FLAGS_PITCH;
  302.         ddsh.dwPitchOrLinearSize = dwPitch;
  303.         break;
  304.     case D3DFMT_A1R5G5B5:
  305.         ddsh.ddspf = DDSPF_A1R5G5B5;
  306.         ddsh.dwHeaderFlags |= DDS_HEADER_FLAGS_PITCH;
  307.         ddsh.dwPitchOrLinearSize = dwPitch;
  308.         break;
  309.     case D3DFMT_A4R4G4B4:
  310.         ddsh.ddspf = DDSPF_A4R4G4B4;
  311.         ddsh.dwHeaderFlags |= DDS_HEADER_FLAGS_PITCH;
  312.         ddsh.dwPitchOrLinearSize = dwPitch;
  313.         break;
  314.     case D3DFMT_R8G8B8:
  315.         ddsh.ddspf = DDSPF_R8G8B8;
  316.         ddsh.dwHeaderFlags |= DDS_HEADER_FLAGS_PITCH;
  317.         ddsh.dwPitchOrLinearSize = dwPitch;
  318.         break;
  319.     case D3DFMT_R5G6B5:
  320.         ddsh.ddspf = DDSPF_R5G6B5;
  321.         ddsh.dwHeaderFlags |= DDS_HEADER_FLAGS_PITCH;
  322.         ddsh.dwPitchOrLinearSize = dwPitch;
  323.         break;
  324.     default:
  325.         return E_FAIL;
  326.     }
  327.  
  328.     ar.Write(&ddsh, sizeof(ddsh));
  329.  
  330.     if (pvoltex != NULL)
  331.     {
  332.         if (FAILED(hr = SaveAllVolumeSurfaces(pvoltex, ar)))
  333.             return hr;
  334.     }
  335.     else if (pmiptex != NULL)
  336.     {
  337.         if (FAILED(hr = SaveAllMipSurfaces(ptex, D3DCUBEMAP_FACE_FORCE_DWORD, ar)))
  338.             return hr;
  339.     }
  340.     else
  341.     {
  342.         if (FAILED(hr = SaveAllMipSurfaces(ptex, D3DCUBEMAP_FACE_POSITIVE_X, ar)))
  343.             return hr;
  344.         if (FAILED(hr = SaveAllMipSurfaces(ptex, D3DCUBEMAP_FACE_NEGATIVE_X, ar)))
  345.             return hr;
  346.         if (FAILED(hr = SaveAllMipSurfaces(ptex, D3DCUBEMAP_FACE_POSITIVE_Y, ar)))
  347.             return hr;
  348.         if (FAILED(hr = SaveAllMipSurfaces(ptex, D3DCUBEMAP_FACE_NEGATIVE_Y, ar)))
  349.             return hr;
  350.         if (FAILED(hr = SaveAllMipSurfaces(ptex, D3DCUBEMAP_FACE_POSITIVE_Z, ar)))
  351.             return hr;
  352.         if (FAILED(hr = SaveAllMipSurfaces(ptex, D3DCUBEMAP_FACE_NEGATIVE_Z, ar)))
  353.             return hr;
  354.     }
  355.  
  356.     return S_OK;
  357. }
  358.  
  359.  
  360. HRESULT CDxtexDoc::SaveAllMipSurfaces(LPDIRECT3DBASETEXTURE8 ptex, D3DCUBEMAP_FACES FaceType, CArchive& ar)
  361. {
  362.     HRESULT hr;
  363.     LPDIRECT3DSURFACE8 psurf;
  364.     D3DSURFACE_DESC sd;
  365.     UINT iLevel;
  366.     D3DLOCKED_RECT lr;
  367.     LPDIRECT3DTEXTURE8 pmiptex = NULL;
  368.     LPDIRECT3DCUBETEXTURE8 pcubetex = NULL;
  369.  
  370.     if (FaceType == D3DCUBEMAP_FACE_FORCE_DWORD)
  371.         pmiptex = (LPDIRECT3DTEXTURE8)ptex;
  372.     else
  373.         pcubetex = (LPDIRECT3DCUBETEXTURE8)ptex;
  374.  
  375.     for (iLevel = 0; iLevel < m_numMips; iLevel++)
  376.     {
  377.         if (pmiptex != NULL)
  378.             hr = pmiptex->GetSurfaceLevel(iLevel, &psurf);
  379.         else
  380.             hr = pcubetex->GetCubeMapSurface(FaceType, iLevel, &psurf);
  381.         if (FAILED(hr))
  382.             return hr;
  383.         psurf->GetDesc(&sd);
  384.         if (pmiptex != NULL)
  385.             hr = pmiptex->LockRect(iLevel, &lr, NULL, 0);
  386.         else
  387.             hr = pcubetex->LockRect(FaceType, iLevel, &lr, NULL, 0);
  388.         if (FAILED(hr))
  389.             return hr;
  390.         if (sd.Format == D3DFMT_DXT1 ||
  391.             sd.Format == D3DFMT_DXT2 ||
  392.             sd.Format == D3DFMT_DXT3 ||
  393.             sd.Format == D3DFMT_DXT4 ||
  394.             sd.Format == D3DFMT_DXT5)
  395.         {
  396.             ar.Write(lr.pBits, sd.Size);
  397.         }
  398.         else
  399.         {
  400.             DWORD yp;
  401.             BYTE* pbDest = (BYTE*)lr.pBits;
  402.             LONG dataBytesPerRow = 0;
  403.             if (sd.Format == D3DFMT_A8R8G8B8)
  404.                 dataBytesPerRow = 4 * sd.Width;
  405.             else if (sd.Format == D3DFMT_R8G8B8)
  406.                 dataBytesPerRow = 3 * sd.Width;
  407.             else
  408.                 dataBytesPerRow = 2 * sd.Width;
  409.             for (yp = 0; yp < sd.Height; yp++)
  410.             {
  411.                 ar.Write(pbDest, dataBytesPerRow);
  412.                 pbDest += lr.Pitch;
  413.             }
  414.         }
  415.         if (pmiptex != NULL)
  416.             hr = pmiptex->UnlockRect(iLevel);
  417.         else
  418.             hr = pcubetex->UnlockRect(FaceType, iLevel);
  419.     }
  420.  
  421.     return S_OK;
  422. }
  423.  
  424.  
  425. HRESULT CDxtexDoc::SaveAllVolumeSurfaces(LPDIRECT3DVOLUMETEXTURE8 pvoltex, CArchive& ar)
  426. {
  427.     HRESULT hr;
  428.     D3DVOLUME_DESC vd;
  429.     D3DBOX box;
  430.     D3DLOCKED_BOX lb;
  431.     UINT iLevel;
  432.     UINT numBytesPerRow;
  433.     BYTE* pbSlice;
  434.     BYTE* pbRow;
  435.     UINT zp;
  436.     UINT yp;
  437.  
  438.     for (iLevel = 0; iLevel < m_numMips; iLevel++)
  439.     {
  440.         pvoltex->GetLevelDesc(iLevel, &vd);
  441.         box.Left = 0;
  442.         box.Right = vd.Width;
  443.         box.Top = 0;
  444.         box.Bottom = vd.Height;
  445.         box.Front = 0;
  446.         box.Back = vd.Depth;
  447.         hr = pvoltex->LockBox(iLevel, &lb, &box, 0);
  448.         if (FAILED(hr))
  449.             return hr;
  450.         switch(vd.Format)
  451.         {
  452.         case D3DFMT_A8R8G8B8:
  453.             numBytesPerRow = 4 * vd.Width;
  454.             break;
  455.         case D3DFMT_R8G8B8:
  456.             numBytesPerRow = 3 * vd.Width;
  457.             break;
  458.         case D3DFMT_A1R5G5B5:
  459.         case D3DFMT_A4R4G4B4:
  460.         case D3DFMT_R5G6B5:
  461.             numBytesPerRow = 2 * vd.Width;
  462.             break;
  463.         default:
  464.             return E_FAIL;
  465.         }
  466.         pbSlice = (BYTE*)lb.pBits;
  467.         for (zp = 0; zp < vd.Depth; zp++)
  468.         {
  469.             pbRow = pbSlice;
  470.             for (yp = 0; yp < vd.Height; yp++)
  471.             {
  472.                 ar.Write(pbRow, numBytesPerRow);
  473.                 pbRow += lb.RowPitch;
  474.             }
  475.             pbSlice += lb.SlicePitch;
  476.         }
  477.  
  478.         pvoltex->UnlockBox(iLevel);
  479.     }
  480.  
  481.     return S_OK;
  482. }
  483.  
  484.  
  485. HRESULT CDxtexDoc::LoadDDS(LPDIRECT3DBASETEXTURE8* pptex, CArchive& ar)
  486. {
  487.  
  488.     HRESULT hr;
  489.     DWORD dwMagic;
  490.     DDS_HEADER ddsh;
  491.     LPDIRECT3DDEVICE8 pd3ddev = PDxtexApp()->Pd3ddev();
  492.     LPDIRECT3DTEXTURE8 pmiptex = NULL;
  493.     LPDIRECT3DCUBETEXTURE8 pcubetex = NULL;
  494.     LPDIRECT3DVOLUMETEXTURE8 pvoltex = NULL;
  495.  
  496.     *pptex = NULL;
  497.     
  498.     ar.Read(&dwMagic, sizeof(dwMagic));
  499.     if (dwMagic != MAKEFOURCC('D','D','S',' '))
  500.         return E_FAIL;
  501.     ar.Read(&ddsh, sizeof(ddsh));
  502.     if (ddsh.dwSize != sizeof(ddsh))
  503.         return E_FAIL;
  504.     m_dwWidth = ddsh.dwWidth;
  505.     m_dwHeight = ddsh.dwHeight;
  506.     m_numMips = ddsh.dwMipMapCount;
  507.     if (m_numMips == 0)
  508.         m_numMips = 1;
  509.     m_dwCubeMapFlags = (ddsh.dwCubemapFlags & DDS_CUBEMAP_ALLFACES);
  510.     if (ddsh.dwHeaderFlags & DDS_HEADER_FLAGS_VOLUME)
  511.         m_dwDepth = ddsh.dwDepth;
  512.     else
  513.         m_dwDepth = 0;
  514.  
  515.     D3DFORMAT fmt;
  516.     if (!IsVolumeMap() && ddsh.ddspf.dwFourCC == D3DFMT_DXT1)
  517.         fmt = D3DFMT_DXT1;
  518.     else if (!IsVolumeMap() && ddsh.ddspf.dwFourCC == D3DFMT_DXT2)
  519.         fmt = D3DFMT_DXT2;
  520.     else if (!IsVolumeMap() && ddsh.ddspf.dwFourCC == D3DFMT_DXT3)
  521.         fmt = D3DFMT_DXT3;
  522.     else if (!IsVolumeMap() && ddsh.ddspf.dwFourCC == D3DFMT_DXT4)
  523.         fmt = D3DFMT_DXT4;
  524.     else if (!IsVolumeMap() && ddsh.ddspf.dwFourCC == D3DFMT_DXT5)
  525.         fmt = D3DFMT_DXT5;
  526.     else if (ddsh.ddspf.dwFlags == DDS_RGBA && ddsh.ddspf.dwRGBBitCount == 32 && ddsh.ddspf.dwABitMask == 0xff000000)
  527.         fmt = D3DFMT_A8R8G8B8;
  528.     else if (ddsh.ddspf.dwFlags == DDS_RGB  && ddsh.ddspf.dwRGBBitCount == 24)
  529.         fmt = D3DFMT_R8G8B8;
  530.     else if (ddsh.ddspf.dwFlags == DDS_RGB  && ddsh.ddspf.dwRGBBitCount == 16 && ddsh.ddspf.dwGBitMask == 0x000007e0)
  531.         fmt = D3DFMT_R5G6B5;
  532.     else if (ddsh.ddspf.dwFlags == DDS_RGBA && ddsh.ddspf.dwRGBBitCount == 16 && ddsh.ddspf.dwABitMask == 0x00008000)
  533.         fmt = D3DFMT_A1R5G5B5;
  534.     else if (ddsh.ddspf.dwFlags == DDS_RGBA && ddsh.ddspf.dwRGBBitCount == 16 && ddsh.ddspf.dwABitMask == 0x0000f000)
  535.         fmt = D3DFMT_A4R4G4B4;
  536.     else
  537.         return E_FAIL; // unknown fmt
  538.  
  539.     if (IsVolumeMap())
  540.     {
  541.         if (FAILED(hr = pd3ddev->CreateVolumeTexture(m_dwWidth, m_dwHeight, m_dwDepth, m_numMips,
  542.             0, fmt, D3DPOOL_SYSTEMMEM, &pvoltex)))
  543.         {
  544.             return hr;
  545.         }
  546.  
  547.         if (FAILED(hr = LoadAllVolumeSurfaces(pvoltex, ar)))
  548.             return hr;
  549.  
  550.         *pptex = pvoltex;
  551.     }
  552.     else if (IsCubeMap())
  553.     {
  554.         if (FAILED(hr = pd3ddev->CreateCubeTexture(m_dwWidth, m_numMips, 
  555.              0, fmt, D3DPOOL_MANAGED, &pcubetex)))
  556.         {
  557.             return hr;
  558.         }
  559.  
  560.         // Cubemaps created with the DX7 version of DxTex may skip some
  561.         // cube faces.  ddsh.dwCubeMapFlags indicates which faces are
  562.         // present.  If you only care about loading post-DX7 cubemaps, you
  563.         // don't have to check these flags -- just load each face in sequence.
  564.  
  565.         // REVIEW: zero out surfaces of missing faces?
  566.  
  567.         if (m_dwCubeMapFlags & DDS_CUBEMAP_POSITIVEX)
  568.         {
  569.             if (FAILED(hr = LoadAllMipSurfaces(pcubetex, D3DCUBEMAP_FACE_POSITIVE_X, ar)))
  570.                 return hr;
  571.         }
  572.  
  573.         if (m_dwCubeMapFlags & DDS_CUBEMAP_NEGATIVEX)
  574.         {
  575.             if (FAILED(hr = LoadAllMipSurfaces(pcubetex, D3DCUBEMAP_FACE_NEGATIVE_X, ar)))
  576.                 return hr;
  577.         }
  578.  
  579.         if (m_dwCubeMapFlags & DDS_CUBEMAP_POSITIVEY)
  580.         {
  581.             if (FAILED(hr = LoadAllMipSurfaces(pcubetex, D3DCUBEMAP_FACE_POSITIVE_Y, ar)))
  582.                 return hr;
  583.         }
  584.  
  585.         if (m_dwCubeMapFlags & DDS_CUBEMAP_NEGATIVEY)
  586.         {
  587.             if (FAILED(hr = LoadAllMipSurfaces(pcubetex, D3DCUBEMAP_FACE_NEGATIVE_Y, ar)))
  588.                 return hr;
  589.         }
  590.  
  591.         if (m_dwCubeMapFlags & DDS_CUBEMAP_POSITIVEZ)
  592.         {
  593.             if (FAILED(hr = LoadAllMipSurfaces(pcubetex, D3DCUBEMAP_FACE_POSITIVE_Z, ar)))
  594.                 return hr;
  595.         }
  596.  
  597.         if (m_dwCubeMapFlags & DDS_CUBEMAP_NEGATIVEZ)
  598.         {
  599.             if (FAILED(hr = LoadAllMipSurfaces(pcubetex, D3DCUBEMAP_FACE_NEGATIVE_Z, ar)))
  600.                 return hr;
  601.         }
  602.  
  603.         *pptex = pcubetex;
  604.     }
  605.     else
  606.     {
  607.         if (FAILED(hr = pd3ddev->CreateTexture(m_dwWidth, m_dwHeight, m_numMips, 
  608.              0, fmt, D3DPOOL_MANAGED, &pmiptex)))
  609.         {
  610.             return hr;
  611.         }
  612.  
  613.         if (FAILED(hr = LoadAllMipSurfaces(pmiptex, D3DCUBEMAP_FACE_FORCE_DWORD, ar)))
  614.             return hr;
  615.  
  616.         *pptex = pmiptex;
  617.     }
  618.  
  619.     return S_OK;
  620. }
  621.  
  622.  
  623. HRESULT CDxtexDoc::LoadAllMipSurfaces(LPDIRECT3DBASETEXTURE8 ptex, D3DCUBEMAP_FACES FaceType, CArchive& ar)
  624. {
  625.     HRESULT hr;
  626.     LPDIRECT3DSURFACE8 psurf;
  627.     D3DSURFACE_DESC sd;
  628.     UINT iLevel;
  629.     D3DLOCKED_RECT lr;
  630.     LPDIRECT3DTEXTURE8 pmiptex = NULL;
  631.     LPDIRECT3DCUBETEXTURE8 pcubetex = NULL;
  632.     DWORD dwBytesPerRow;
  633.  
  634.     if (FaceType == D3DCUBEMAP_FACE_FORCE_DWORD)
  635.         pmiptex = (LPDIRECT3DTEXTURE8)ptex;
  636.     else
  637.         pcubetex = (LPDIRECT3DCUBETEXTURE8)ptex;
  638.  
  639.     for (iLevel = 0; iLevel < m_numMips; iLevel++)
  640.     {
  641.         if (pmiptex != NULL)
  642.             hr = pmiptex->GetSurfaceLevel(iLevel, &psurf);
  643.         else
  644.             hr = pcubetex->GetCubeMapSurface(FaceType, iLevel, &psurf);
  645.         if (FAILED(hr))
  646.             return hr;
  647.         psurf->GetDesc(&sd);
  648.         switch (sd.Format)
  649.         {
  650.         case D3DFMT_DXT1:
  651.         case D3DFMT_DXT2:
  652.         case D3DFMT_DXT3:
  653.         case D3DFMT_DXT4:
  654.         case D3DFMT_DXT5:
  655.             dwBytesPerRow = 0; // magic value indicates texture's memory is contiguous
  656.             break;
  657.         case D3DFMT_A8R8G8B8:
  658.             dwBytesPerRow = 4 * sd.Width;
  659.             break;
  660.         case D3DFMT_R8G8B8:
  661.             dwBytesPerRow = 3 * sd.Width;
  662.             break;
  663.         case D3DFMT_A1R5G5B5:
  664.         case D3DFMT_A4R4G4B4:
  665.         case D3DFMT_R5G6B5:
  666.             dwBytesPerRow = 2 * sd.Width;
  667.             break;
  668.         default:
  669.             return E_FAIL;
  670.         }
  671.             
  672.         if (pmiptex != NULL)
  673.             hr = pmiptex->LockRect(iLevel, &lr, NULL, 0);
  674.         else
  675.             hr = pcubetex->LockRect(FaceType, iLevel, &lr, NULL, 0);
  676.         if (FAILED(hr))
  677.             return hr;
  678.         if (dwBytesPerRow == 0)
  679.         {
  680.             ar.Read(lr.pBits, sd.Size);
  681.         }
  682.         else
  683.         {
  684.             DWORD yp;
  685.             BYTE* pbDest = (BYTE*)lr.pBits;
  686.             for (yp = 0; yp < sd.Height; yp++)
  687.             {
  688.                 ar.Read(pbDest, dwBytesPerRow);
  689.                 pbDest += lr.Pitch;
  690.             }
  691.         }
  692.  
  693.         if (pmiptex != NULL)
  694.             hr = pmiptex->UnlockRect(iLevel);
  695.         else
  696.             hr = pcubetex->UnlockRect(FaceType, iLevel);
  697.         ReleasePpo(&psurf);
  698.     }
  699.  
  700.     return S_OK;
  701. }
  702.  
  703.  
  704. HRESULT CDxtexDoc::LoadAllVolumeSurfaces(LPDIRECT3DVOLUMETEXTURE8 pvoltex, CArchive& ar)
  705. {
  706.     HRESULT hr;
  707.     D3DVOLUME_DESC vd;
  708.     D3DBOX box;
  709.     D3DLOCKED_BOX lb;
  710.     UINT iLevel;
  711.     UINT numBytesPerRow;
  712.     BYTE* pbSlice;
  713.     BYTE* pbRow;
  714.     UINT zp;
  715.     UINT yp;
  716.  
  717.     for (iLevel = 0; iLevel < m_numMips; iLevel++)
  718.     {
  719.         pvoltex->GetLevelDesc(iLevel, &vd);
  720.         box.Left = 0;
  721.         box.Right = vd.Width;
  722.         box.Top = 0;
  723.         box.Bottom = vd.Height;
  724.         box.Front = 0;
  725.         box.Back = vd.Depth;
  726.         hr = pvoltex->LockBox(iLevel, &lb, &box, 0);
  727.         if (FAILED(hr))
  728.             return hr;
  729.         switch(vd.Format)
  730.         {
  731.         case D3DFMT_A8R8G8B8:
  732.             numBytesPerRow = 4 * vd.Width;
  733.             break;
  734.         default:
  735.             return E_FAIL;
  736.         }
  737.         pbSlice = (BYTE*)lb.pBits;
  738.         for (zp = 0; zp < vd.Depth; zp++)
  739.         {
  740.             pbRow = pbSlice;
  741.             for (yp = 0; yp < vd.Height; yp++)
  742.             {
  743.                 ar.Read(pbRow, numBytesPerRow);
  744.                 pbRow += lb.RowPitch;
  745.             }
  746.             pbSlice += lb.SlicePitch;
  747.         }
  748.  
  749.         pvoltex->UnlockBox(iLevel);
  750.     }
  751.  
  752.     return S_OK;
  753. }
  754.  
  755.  
  756. /////////////////////////////////////////////////////////////////////////////
  757. // CDxtexDoc commands
  758.  
  759. HRESULT CDxtexDoc::LoadBmp(CString& strPath)
  760. {
  761.     HRESULT hr;
  762.  
  763.     LPDIRECT3DDEVICE8 pd3ddev;
  764.     LPDIRECT3DTEXTURE8 ptex;
  765.  
  766.     pd3ddev = PDxtexApp()->Pd3ddev();
  767.     hr = D3DXCreateTextureFromFileEx(pd3ddev, strPath, D3DX_DEFAULT, 
  768.         D3DX_DEFAULT, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, 
  769.         D3DX_FILTER_POINT, D3DX_FILTER_POINT, 0, NULL, NULL, &ptex);
  770.     if (FAILED(hr))
  771.         return hr;
  772.  
  773.     // Look for "foo_a.bmp" for alpha channel
  774.     int i = strPath.ReverseFind('.');
  775.     strPath = strPath.Left(i) + "_a.bmp";
  776.     CFileStatus status;
  777.     if (CFile::GetStatus(strPath, status))
  778.     {
  779.         LPDIRECT3DSURFACE8 psurf;
  780.  
  781.         hr = ptex->GetSurfaceLevel(0, &psurf);
  782.         if (FAILED(hr))
  783.             return hr;
  784.  
  785.         hr = LoadAlphaIntoSurface(strPath, psurf);
  786.         ReleasePpo(&psurf);
  787.         if (FAILED(hr))
  788.             return hr;
  789.     }
  790.     
  791.     // Ensure that source image dimensions are power of 2
  792.     D3DSURFACE_DESC sd;
  793.     ptex->GetLevelDesc(0, &sd);
  794.     m_dwWidth = sd.Width;
  795.     m_dwHeight = sd.Height;
  796.  
  797.     LONG lwTempW;
  798.     LONG lwTempH;
  799.     lwTempW = sd.Width;
  800.     lwTempH = sd.Height;
  801.     while ((lwTempW & 1) == 0)
  802.         lwTempW = lwTempW >> 1;
  803.     while ((lwTempH & 1) == 0)
  804.         lwTempH = lwTempH >> 1;
  805.     if (lwTempW != 1 || lwTempH != 1)
  806.     {
  807.         AfxMessageBox(ID_ERROR_NOTPOW2);
  808.         ReleasePpo(&ptex);
  809.         return E_FAIL;
  810.     }
  811.  
  812.     m_numMips = 1;
  813.  
  814.     ReleasePpo(&m_ptexOrig);
  815.     m_ptexOrig = ptex;
  816.  
  817.     m_strTitle.Empty();
  818.     m_strPathName.Empty();
  819.     SetModifiedFlag(TRUE);
  820.     
  821.     return S_OK;
  822. }
  823.  
  824.  
  825. HRESULT CDxtexDoc::LoadAlphaBmp(CString& strPath)
  826. {
  827.     HRESULT hr;
  828.     LPDIRECT3DTEXTURE8 pmiptex;
  829.     LPDIRECT3DSURFACE8 psurf;
  830.  
  831.     if (IsCubeMap())
  832.         return E_FAIL;
  833.  
  834.     pmiptex = (LPDIRECT3DTEXTURE8)m_ptexOrig;
  835.     hr = pmiptex->GetSurfaceLevel(0, &psurf);
  836.     if (FAILED(hr))
  837.         return hr;
  838.  
  839.     hr = LoadAlphaIntoSurface(strPath, psurf);
  840.     ReleasePpo(&psurf);
  841.     if (FAILED(hr))
  842.         return hr;
  843.     
  844.     UpdateAllViews(NULL, 1); // tell CView to pick up new surface pointers
  845.     return S_OK;
  846. }
  847.  
  848.  
  849. HRESULT CDxtexDoc::Compress(D3DFORMAT fmtTo, BOOL bSwitchView)
  850. {
  851.     HRESULT hr;
  852.     LPDIRECT3DDEVICE8 pd3ddev = PDxtexApp()->Pd3ddev();
  853.     LPDIRECT3DTEXTURE8 pmiptex;
  854.     LPDIRECT3DCUBETEXTURE8 pcubetex;
  855.     LPDIRECT3DVOLUMETEXTURE8 pvoltex;
  856.     D3DFORMAT fmtFrom;
  857.     LPDIRECT3DTEXTURE8 pmiptexNew;
  858.     LPDIRECT3DCUBETEXTURE8 pcubetexNew;
  859.     LPDIRECT3DVOLUMETEXTURE8 pvoltexNew;
  860.  
  861.     if (IsVolumeMap())
  862.     {
  863.         if (fmtTo == D3DFMT_DXT1 ||
  864.             fmtTo == D3DFMT_DXT2 ||
  865.             fmtTo == D3DFMT_DXT3 ||
  866.             fmtTo == D3DFMT_DXT4 ||
  867.             fmtTo == D3DFMT_DXT5)
  868.         {
  869.             return E_FAIL;
  870.         }
  871.         pvoltex = (LPDIRECT3DVOLUMETEXTURE8)m_ptexOrig;
  872.         D3DVOLUME_DESC vd;
  873.         pvoltex->GetLevelDesc(0, &vd);
  874.         fmtFrom = vd.Format;
  875.     }
  876.     else if (IsCubeMap())
  877.     {
  878.         pcubetex = (LPDIRECT3DCUBETEXTURE8)m_ptexOrig;
  879.         D3DSURFACE_DESC sd;
  880.         pcubetex->GetLevelDesc(0, &sd);
  881.         fmtFrom = sd.Format;
  882.     }
  883.     else
  884.     {
  885.         pmiptex = (LPDIRECT3DTEXTURE8)m_ptexOrig;
  886.         D3DSURFACE_DESC sd;
  887.         pmiptex->GetLevelDesc(0, &sd);
  888.         fmtFrom = sd.Format;
  889.     }
  890.  
  891.     if (fmtFrom == D3DFMT_DXT2 || fmtFrom == D3DFMT_DXT4)
  892.     {
  893.         if (fmtTo == D3DFMT_DXT1)
  894.         {
  895.             AfxMessageBox(ID_ERROR_PREMULTTODXT1);
  896.         }
  897.         else if (fmtTo != D3DFMT_DXT2 && fmtTo != D3DFMT_DXT4)
  898.         {
  899.             AfxMessageBox(ID_ERROR_PREMULTALPHA);
  900.             return S_OK;
  901.         }
  902.     }
  903.  
  904.     if (IsVolumeMap())
  905.     {
  906.         hr = pd3ddev->CreateVolumeTexture(m_dwWidth, m_dwHeight, m_dwDepth, m_numMips,
  907.             0, fmtTo, D3DPOOL_SYSTEMMEM, &pvoltexNew);
  908.         if (FAILED(hr))
  909.             return hr;
  910.         ReleasePpo(&m_ptexNew);
  911.         m_ptexNew = pvoltexNew;
  912.         if (FAILED(BltAllLevels(D3DCUBEMAP_FACE_FORCE_DWORD, m_ptexOrig, m_ptexNew)))
  913.             return hr;
  914.     }
  915.     else if (IsCubeMap())
  916.     {
  917.         hr = pd3ddev->CreateCubeTexture(m_dwWidth, m_numMips, 
  918.              0, fmtTo, D3DPOOL_MANAGED, &pcubetexNew);
  919.         if (FAILED(hr))
  920.             return hr;
  921.         ReleasePpo(&m_ptexNew);
  922.         m_ptexNew = pcubetexNew;
  923.         if (FAILED(hr = BltAllLevels(D3DCUBEMAP_FACE_NEGATIVE_X, m_ptexOrig, m_ptexNew)))
  924.             return hr;
  925.         if (FAILED(hr = BltAllLevels(D3DCUBEMAP_FACE_POSITIVE_X, m_ptexOrig, m_ptexNew)))
  926.             return hr;
  927.         if (FAILED(hr = BltAllLevels(D3DCUBEMAP_FACE_NEGATIVE_Y, m_ptexOrig, m_ptexNew)))
  928.             return hr;
  929.         if (FAILED(hr = BltAllLevels(D3DCUBEMAP_FACE_POSITIVE_Y, m_ptexOrig, m_ptexNew)))
  930.             return hr;
  931.         if (FAILED(hr = BltAllLevels(D3DCUBEMAP_FACE_NEGATIVE_Z, m_ptexOrig, m_ptexNew)))
  932.             return hr;
  933.         if (FAILED(hr = BltAllLevels(D3DCUBEMAP_FACE_POSITIVE_Z, m_ptexOrig, m_ptexNew)))
  934.             return hr;
  935.     }
  936.     else
  937.     {
  938.         hr = pd3ddev->CreateTexture(m_dwWidth, m_dwHeight, m_numMips, 
  939.              0, fmtTo, D3DPOOL_MANAGED, &pmiptexNew);
  940.         if (FAILED(hr))
  941.             return hr;
  942.         ReleasePpo(&m_ptexNew);
  943.         m_ptexNew = pmiptexNew;
  944.         if (FAILED(BltAllLevels(D3DCUBEMAP_FACE_FORCE_DWORD, m_ptexOrig, m_ptexNew)))
  945.             return hr;
  946.     }
  947.  
  948.     SetModifiedFlag();
  949.     m_bTitleModsChanged = TRUE; // force title bar update
  950.     if (bSwitchView)
  951.         AfxGetMainWnd()->PostMessage(WM_COMMAND, ID_VIEW_COMPRESSED, 0);
  952.  
  953.     return S_OK;
  954. }
  955.  
  956.  
  957. void CDxtexDoc::OnGenerateMipMaps() 
  958. {
  959.     GenerateMipMaps();
  960. }
  961.  
  962.  
  963. void CDxtexDoc::GenerateMipMaps() 
  964. {
  965.     LONG lwTempH;
  966.     LONG lwTempW;
  967.     LONG lwPowsW;
  968.     LONG lwPowsH;
  969.     LPDIRECT3DTEXTURE8 pddsNew = NULL;
  970.     D3DFORMAT fmt;
  971.     HRESULT hr;
  972.     LPDIRECT3DDEVICE8 pd3ddev = PDxtexApp()->Pd3ddev();
  973.     LPDIRECT3DTEXTURE8 pmiptex = NULL;
  974.     LPDIRECT3DCUBETEXTURE8 pcubetex = NULL;
  975.     LPDIRECT3DVOLUMETEXTURE8 pvoltex = NULL;
  976.     LPDIRECT3DTEXTURE8 pmiptexNew = NULL;
  977.     LPDIRECT3DCUBETEXTURE8 pcubetexNew = NULL;
  978.     LPDIRECT3DVOLUMETEXTURE8 pvoltexNew = NULL;
  979.     LPDIRECT3DSURFACE8 psurfSrc;
  980.     LPDIRECT3DSURFACE8 psurfDest;
  981.     LPDIRECT3DVOLUME8 pvolSrc;
  982.     LPDIRECT3DVOLUME8 pvolDest;
  983.  
  984.     if (IsVolumeMap())
  985.         pvoltex = (LPDIRECT3DVOLUMETEXTURE8)m_ptexOrig;
  986.     else if (IsCubeMap())
  987.         pcubetex = (LPDIRECT3DCUBETEXTURE8)m_ptexOrig;
  988.     else
  989.         pmiptex = (LPDIRECT3DTEXTURE8)m_ptexOrig;
  990.  
  991.     if (pvoltex != NULL)
  992.     {
  993.         D3DVOLUME_DESC vd;
  994.         pvoltex->GetLevelDesc(0, &vd);
  995.         fmt = vd.Format;
  996.     }
  997.     else if (pcubetex != NULL)
  998.     {
  999.         D3DSURFACE_DESC sd;
  1000.         pcubetex->GetLevelDesc(0, &sd);
  1001.         fmt = sd.Format;
  1002.     }
  1003.     else
  1004.     {
  1005.         D3DSURFACE_DESC sd;
  1006.         pmiptex->GetLevelDesc(0, &sd);
  1007.         fmt = sd.Format;
  1008.     }
  1009.  
  1010.     // Ensure that source image is power of 2
  1011.     lwTempW = m_dwWidth;
  1012.     lwTempH = m_dwHeight;
  1013.     lwPowsW = 1;
  1014.     lwPowsH = 1;
  1015.     while ((lwTempW & 1) == 0)
  1016.     {
  1017.         lwPowsW++;
  1018.         lwTempW = lwTempW >> 1;
  1019.     }
  1020.     while ((lwTempH & 1) == 0)
  1021.     {
  1022.         lwPowsH++;
  1023.         lwTempH = lwTempH >> 1;
  1024.     }
  1025.     if (lwTempW != 1 || lwTempH != 1)
  1026.     {
  1027.         AfxMessageBox(ID_ERROR_NOTPOW2);
  1028.         return;
  1029.     }
  1030.     m_numMips = lwPowsW > lwPowsH ? lwPowsW : lwPowsH;
  1031.  
  1032.     // Create destination mipmap surface - same format as source
  1033.     if (pvoltex != NULL)
  1034.     {
  1035.         if (FAILED(hr = pd3ddev->CreateVolumeTexture(m_dwWidth, m_dwHeight, m_dwDepth, 
  1036.             m_numMips, 0, fmt, D3DPOOL_SYSTEMMEM, &pvoltexNew)))
  1037.         {
  1038.             goto LFail;
  1039.         }
  1040.         hr = pvoltex->GetVolumeLevel(0, &pvolSrc);
  1041.         hr = pvoltexNew->GetVolumeLevel(0, &pvolDest);
  1042.         hr = D3DXLoadVolumeFromVolume(pvolDest, NULL, NULL, pvolSrc, NULL, NULL, 
  1043.             D3DX_FILTER_TRIANGLE, 0);
  1044.         ReleasePpo(&pvolSrc);
  1045.         ReleasePpo(&pvolDest);
  1046.         hr = D3DXFilterVolumeTexture(pvoltexNew, NULL, 0, D3DX_FILTER_TRIANGLE);
  1047.     }
  1048.     else if (pmiptex != NULL)
  1049.     {
  1050.         if (FAILED(hr = pd3ddev->CreateTexture(m_dwWidth, m_dwHeight, m_numMips, 
  1051.              0, fmt, D3DPOOL_MANAGED, &pmiptexNew)))
  1052.         {
  1053.             goto LFail;
  1054.         }
  1055.         hr = pmiptex->GetSurfaceLevel(0, &psurfSrc);
  1056.         hr = pmiptexNew->GetSurfaceLevel(0, &psurfDest);
  1057.         hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL, 
  1058.             D3DX_FILTER_TRIANGLE, 0);
  1059.         ReleasePpo(&psurfSrc);
  1060.         ReleasePpo(&psurfDest);
  1061.         hr = D3DXFilterTexture(pmiptexNew, NULL, 0, D3DX_FILTER_TRIANGLE);
  1062.     }
  1063.     else
  1064.     {
  1065.         if (FAILED(hr = pd3ddev->CreateCubeTexture(m_dwWidth, m_numMips, 
  1066.              0, fmt, D3DPOOL_MANAGED, &pcubetexNew)))
  1067.         {
  1068.             goto LFail;
  1069.         }
  1070.         hr = pcubetex->GetCubeMapSurface(D3DCUBEMAP_FACE_POSITIVE_X, 0, &psurfSrc);
  1071.         hr = pcubetexNew->GetCubeMapSurface(D3DCUBEMAP_FACE_POSITIVE_X, 0, &psurfDest);
  1072.         hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL, 
  1073.             D3DX_FILTER_TRIANGLE, 0);
  1074.         ReleasePpo(&psurfSrc);
  1075.         ReleasePpo(&psurfDest);
  1076.         hr = pcubetex->GetCubeMapSurface(D3DCUBEMAP_FACE_NEGATIVE_X, 0, &psurfSrc);
  1077.         hr = pcubetexNew->GetCubeMapSurface(D3DCUBEMAP_FACE_NEGATIVE_X, 0, &psurfDest);
  1078.         hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL, 
  1079.             D3DX_FILTER_TRIANGLE, 0);
  1080.         ReleasePpo(&psurfSrc);
  1081.         ReleasePpo(&psurfDest);
  1082.         hr = pcubetex->GetCubeMapSurface(D3DCUBEMAP_FACE_POSITIVE_Y, 0, &psurfSrc);
  1083.         hr = pcubetexNew->GetCubeMapSurface(D3DCUBEMAP_FACE_POSITIVE_Y, 0, &psurfDest);
  1084.         hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL, 
  1085.             D3DX_FILTER_TRIANGLE, 0);
  1086.         ReleasePpo(&psurfSrc);
  1087.         ReleasePpo(&psurfDest);
  1088.         hr = pcubetex->GetCubeMapSurface(D3DCUBEMAP_FACE_NEGATIVE_Y, 0, &psurfSrc);
  1089.         hr = pcubetexNew->GetCubeMapSurface(D3DCUBEMAP_FACE_NEGATIVE_Y, 0, &psurfDest);
  1090.         hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL, 
  1091.             D3DX_FILTER_TRIANGLE, 0);
  1092.         ReleasePpo(&psurfSrc);
  1093.         ReleasePpo(&psurfDest);
  1094.         hr = pcubetex->GetCubeMapSurface(D3DCUBEMAP_FACE_POSITIVE_Z, 0, &psurfSrc);
  1095.         hr = pcubetexNew->GetCubeMapSurface(D3DCUBEMAP_FACE_POSITIVE_Z, 0, &psurfDest);
  1096.         hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL, 
  1097.             D3DX_FILTER_TRIANGLE, 0);
  1098.         ReleasePpo(&psurfSrc);
  1099.         ReleasePpo(&psurfDest);
  1100.         hr = pcubetex->GetCubeMapSurface(D3DCUBEMAP_FACE_NEGATIVE_Z, 0, &psurfSrc);
  1101.         hr = pcubetexNew->GetCubeMapSurface(D3DCUBEMAP_FACE_NEGATIVE_Z, 0, &psurfDest);
  1102.         hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL, 
  1103.             D3DX_FILTER_TRIANGLE, 0);
  1104.         ReleasePpo(&psurfSrc);
  1105.         ReleasePpo(&psurfDest);
  1106.         hr = D3DXFilterCubeTexture(pcubetexNew, NULL, 0, D3DX_FILTER_TRIANGLE);
  1107.     }
  1108.  
  1109.     ReleasePpo(&m_ptexOrig);
  1110.     if (pvoltexNew != NULL)
  1111.         m_ptexOrig = pvoltexNew;
  1112.     else if (pcubetexNew != NULL)
  1113.         m_ptexOrig = pcubetexNew;
  1114.     else
  1115.         m_ptexOrig = pmiptexNew;
  1116.  
  1117.     if (m_ptexNew != NULL)
  1118.     {
  1119.         // Rather than filtering down the (probably-compressed) m_ptexNew 
  1120.         // top level, compress each mip level from the (probably-uncompressed)
  1121.         // m_ptexOrig levels.
  1122.         if (pvoltexNew != NULL)
  1123.         {
  1124.             D3DVOLUME_DESC vd;
  1125.             ((LPDIRECT3DVOLUMETEXTURE8)m_ptexNew)->GetLevelDesc(0, &vd);
  1126.             fmt = vd.Format;
  1127.         }
  1128.         else if (pcubetexNew != NULL)
  1129.         {
  1130.             D3DSURFACE_DESC sd;
  1131.             ((LPDIRECT3DTEXTURE8)m_ptexNew)->GetLevelDesc(0, &sd);
  1132.             fmt = sd.Format;
  1133.         }
  1134.         else
  1135.         {
  1136.             D3DSURFACE_DESC sd;
  1137.             ((LPDIRECT3DCUBETEXTURE8)m_ptexNew)->GetLevelDesc(0, &sd);
  1138.             fmt = sd.Format;
  1139.         }
  1140.         Compress(fmt, FALSE);
  1141.     }
  1142.  
  1143.     m_bTitleModsChanged = TRUE; // Generate title bar update
  1144.     UpdateAllViews(NULL, 1); // tell CView to pick up new surface pointers
  1145.     SetModifiedFlag();
  1146.     return;
  1147.  
  1148. LFail:
  1149.     ReleasePpo(&pddsNew);
  1150. }
  1151.  
  1152.  
  1153. void CDxtexDoc::SetPathName(LPCTSTR lpszPathName, BOOL bAddToMRU) 
  1154. {
  1155.     CDocument::SetPathName(lpszPathName, bAddToMRU);
  1156.  
  1157.     TCHAR* pszLeaf = strrchr(lpszPathName, '\\') + 1;
  1158.     TCHAR* pszExtension = strrchr(lpszPathName, '.');
  1159.     if (lstrcmpi(pszExtension, ".dds") != 0)
  1160.     {
  1161.         lstrcpy(pszExtension, "");
  1162.         SetModifiedFlag(TRUE);
  1163.         SetTitle(pszLeaf);
  1164.         m_strPathName.Empty();
  1165.     }
  1166. }
  1167.  
  1168. DWORD CDxtexDoc::NumMips(VOID)
  1169. {
  1170.     return m_numMips;
  1171. }
  1172.  
  1173.  
  1174. void CDxtexDoc::OnFileOpenAlpha() 
  1175. {
  1176.     HRESULT hr;
  1177.     CString fileName;
  1178.     LPDIRECT3DTEXTURE8 pmiptex;
  1179.  
  1180.     if (IsCubeMap() || IsVolumeMap())
  1181.         return;
  1182.     pmiptex = (LPDIRECT3DTEXTURE8)m_ptexOrig;
  1183.  
  1184.     // Premultiplied-alpha files don't support this feature:
  1185.     D3DSURFACE_DESC sd;
  1186.     pmiptex->GetLevelDesc(0, &sd);
  1187.     if (sd.Format == D3DFMT_DXT2 || sd.Format == D3DFMT_DXT4)
  1188.     {
  1189.         AfxMessageBox(ID_ERROR_PREMULTALPHA);
  1190.         return;
  1191.     }
  1192.  
  1193.     if (!PromptForBmp(&fileName))
  1194.         return;
  1195.  
  1196.     LPDIRECT3DSURFACE8 psurf;
  1197.     if (FAILED(hr = pmiptex->GetSurfaceLevel(0, &psurf)))
  1198.         return;
  1199.  
  1200.     if (FAILED(hr = LoadAlphaIntoSurface(fileName, psurf)))
  1201.         return;
  1202.     if (m_numMips > 1)
  1203.         OnGenerateMipMaps();
  1204.     else if (m_ptexNew != NULL)
  1205.     {
  1206.         ((LPDIRECT3DTEXTURE8)m_ptexNew)->GetLevelDesc(0, &sd);
  1207.         Compress(sd.Format, FALSE);
  1208.     }
  1209.     UpdateAllViews(NULL, 1);
  1210. }
  1211.  
  1212.  
  1213. HRESULT CDxtexDoc::LoadAlphaIntoSurface(CString& strPath, LPDIRECT3DSURFACE8 psurf)
  1214. {
  1215.     HRESULT hr;
  1216.     D3DSURFACE_DESC sd;
  1217.     LPDIRECT3DDEVICE8 pd3ddev = PDxtexApp()->Pd3ddev();
  1218.     LPDIRECT3DTEXTURE8 ptexAlpha;
  1219.     LPDIRECT3DSURFACE8 psurfAlpha;
  1220.     LPDIRECT3DSURFACE8 psurfTarget;
  1221.  
  1222.     psurf->GetDesc(&sd);
  1223.  
  1224.     // Load the alpha BMP into psurfAlpha, a new A8R8G8B8 surface
  1225.     hr = D3DXCreateTextureFromFileEx(pd3ddev, strPath, sd.Width, sd.Height, 1, 0, 
  1226.         D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_FILTER_TRIANGLE, 
  1227.         D3DX_FILTER_TRIANGLE, 0, NULL, NULL, &ptexAlpha);
  1228.     hr = ptexAlpha->GetSurfaceLevel(0, &psurfAlpha);
  1229.  
  1230.     // Copy the target surface into an A8R8G8B8 surface
  1231.     hr = pd3ddev->CreateImageSurface(sd.Width, sd.Height, D3DFMT_A8R8G8B8, &psurfTarget);
  1232.     hr = D3DXLoadSurfaceFromSurface(psurfTarget, NULL, NULL, psurf, NULL, NULL, 
  1233.         D3DX_FILTER_TRIANGLE, 0);
  1234.  
  1235.     // Fill in the alpha channels of psurfTarget based on the blue channel of psurfAlpha
  1236.     D3DLOCKED_RECT lrSrc;
  1237.     D3DLOCKED_RECT lrDest;
  1238.  
  1239.     hr = psurfAlpha->LockRect(&lrSrc, NULL, D3DLOCK_READONLY);
  1240.     hr = psurfTarget->LockRect(&lrDest, NULL, 0);
  1241.  
  1242.     DWORD xp;
  1243.     DWORD yp;
  1244.     DWORD* pdwRowSrc = (DWORD*)lrSrc.pBits;
  1245.     DWORD* pdwRowDest = (DWORD*)lrDest.pBits;
  1246.     DWORD* pdwSrc;
  1247.     DWORD* pdwDest;
  1248.     DWORD dwAlpha;
  1249.     LONG dataBytesPerRow = 4 * sd.Width;
  1250.  
  1251.     for (yp = 0; yp < sd.Height; yp++)
  1252.     {
  1253.         pdwSrc = pdwRowSrc;
  1254.         pdwDest = pdwRowDest;
  1255.         for (xp = 0; xp < sd.Width; xp++)
  1256.         {
  1257.             dwAlpha = *pdwSrc << 24;
  1258.             *pdwDest &= 0x00ffffff;
  1259.             *pdwDest |= dwAlpha;
  1260.  
  1261.             pdwSrc++;
  1262.             pdwDest++;
  1263.         }
  1264.         pdwRowSrc += lrSrc.Pitch / 4;
  1265.         pdwRowDest += lrDest.Pitch / 4;
  1266.     }
  1267.  
  1268.     psurfAlpha->UnlockRect();
  1269.     psurfTarget->UnlockRect();
  1270.  
  1271.     // Copy psurfTarget back into real surface
  1272.     hr = D3DXLoadSurfaceFromSurface(psurf, NULL, NULL, psurfTarget, NULL, NULL, 
  1273.         D3DX_FILTER_TRIANGLE, 0);
  1274.     
  1275.     // Release allocated interfaces
  1276.     ReleasePpo(&psurfTarget);
  1277.     ReleasePpo(&psurfAlpha);
  1278.     ReleasePpo(&ptexAlpha);
  1279.  
  1280.     return S_OK;
  1281. }
  1282.  
  1283.  
  1284. BOOL CDxtexDoc::PromptForBmp(CString* pstrPath)
  1285. {
  1286.     CFileDialog dlgFile(TRUE);
  1287.  
  1288.     CString title;
  1289.     VERIFY(title.LoadString(AFX_IDS_OPENFILE));
  1290.  
  1291.     CString strFilter;
  1292.     CString strDefault;
  1293.  
  1294.     strFilter += "Bitmap Files (*.bmp, *.tga)";
  1295.     strFilter += (TCHAR)'\0';   // next string please
  1296.     strFilter += _T("*.bmp;*.tga");
  1297.     strFilter += (TCHAR)'\0';   // last string
  1298.     dlgFile.m_ofn.nMaxCustFilter++;
  1299.  
  1300.     // append the "*.*" all files filter
  1301.     CString allFilter;
  1302.     VERIFY(allFilter.LoadString(AFX_IDS_ALLFILTER));
  1303.     strFilter += allFilter;
  1304.     strFilter += (TCHAR)'\0';   // next string please
  1305.     strFilter += _T("*.*");
  1306.     strFilter += (TCHAR)'\0';   // last string
  1307.     dlgFile.m_ofn.nMaxCustFilter++;
  1308.  
  1309.     dlgFile.m_ofn.lpstrFilter = strFilter;
  1310.     dlgFile.m_ofn.lpstrTitle = title;
  1311.     dlgFile.m_ofn.lpstrFile = pstrPath->GetBuffer(_MAX_PATH);
  1312.  
  1313.     INT_PTR nResult = dlgFile.DoModal();
  1314.     pstrPath->ReleaseBuffer();
  1315.     if (nResult != IDOK)
  1316.         return FALSE;
  1317.     return TRUE;
  1318. }
  1319.  
  1320.  
  1321. void CDxtexDoc::OpenSubsurface(D3DCUBEMAP_FACES FaceType, LONG lwMip, LONG lwSlice)
  1322. {
  1323.     HRESULT hr;
  1324.     CString fileName;
  1325.     LPDIRECT3DDEVICE8 pd3ddev = PDxtexApp()->Pd3ddev();
  1326.     LPDIRECT3DTEXTURE8 ptex = NULL;
  1327.     LPDIRECT3DSURFACE8 psurfOrig = NULL;
  1328.     LPDIRECT3DSURFACE8 psurfNew = NULL;
  1329.  
  1330.     if (!PromptForBmp(&fileName))
  1331.         return;
  1332.  
  1333.     if (IsVolumeMap())
  1334.     {
  1335.         hr = D3DXCreateTextureFromFile(pd3ddev, fileName, &ptex);
  1336.         hr = ptex->GetSurfaceLevel(0, &psurfOrig);
  1337.     }
  1338.     else if (IsCubeMap())
  1339.     {
  1340.         hr = ((LPDIRECT3DCUBETEXTURE8)m_ptexOrig)->GetCubeMapSurface(FaceType, lwMip, &psurfOrig);
  1341.         if (m_ptexNew != NULL)
  1342.             hr = ((LPDIRECT3DCUBETEXTURE8)m_ptexNew)->GetCubeMapSurface(FaceType, lwMip, &psurfNew);
  1343.         hr = D3DXLoadSurfaceFromFile(psurfOrig, NULL, NULL, fileName, NULL, D3DX_FILTER_TRIANGLE, 0, NULL);
  1344.     }
  1345.     else
  1346.     {
  1347.         hr = ((LPDIRECT3DTEXTURE8)m_ptexOrig)->GetSurfaceLevel(lwMip, &psurfOrig);
  1348.         if (m_ptexNew != NULL)
  1349.             hr = ((LPDIRECT3DTEXTURE8)m_ptexNew)->GetSurfaceLevel(lwMip, &psurfNew);
  1350.         hr = D3DXLoadSurfaceFromFile(psurfOrig, NULL, NULL, fileName, NULL, D3DX_FILTER_TRIANGLE, 0, NULL);
  1351.     }
  1352.  
  1353.     // Look for "foo_a.bmp" for alpha channel
  1354.     int i = fileName.ReverseFind('.');
  1355.     fileName = fileName.Left(i) + "_a.bmp";
  1356.     CFileStatus status;
  1357.     if (CFile::GetStatus(fileName, status))
  1358.     {
  1359.         if (FAILED(hr = LoadAlphaIntoSurface(fileName, psurfOrig)))
  1360.             return;
  1361.     }
  1362.  
  1363.     if (IsVolumeMap())
  1364.     {
  1365.         LPDIRECT3DVOLUME8 pvol;
  1366.         hr = ((LPDIRECT3DVOLUMETEXTURE8)m_ptexOrig)->GetVolumeLevel(lwMip, &pvol);
  1367.         hr = LoadVolumeSliceFromSurface(pvol, lwSlice, psurfOrig);
  1368.         ReleasePpo(&pvol);
  1369.         if (m_ptexNew)
  1370.         {
  1371.             hr = ((LPDIRECT3DVOLUMETEXTURE8)m_ptexNew)->GetVolumeLevel(lwMip, &pvol);
  1372.             hr = LoadVolumeSliceFromSurface(pvol, lwSlice, psurfOrig);
  1373.             ReleasePpo(&pvol);
  1374.         }
  1375.     }
  1376.     else if (psurfNew != NULL)
  1377.     {
  1378.         hr = D3DXLoadSurfaceFromSurface(psurfNew, NULL, NULL, psurfOrig, NULL, NULL, D3DX_FILTER_TRIANGLE, 0);
  1379.     }
  1380.  
  1381.     ReleasePpo(&psurfOrig);
  1382.     ReleasePpo(&psurfNew);
  1383.     ReleasePpo(&ptex);
  1384.  
  1385.     SetModifiedFlag(TRUE);
  1386.     UpdateAllViews(NULL, 1);
  1387. }
  1388.  
  1389.  
  1390. void CDxtexDoc::OpenAlphaSubsurface(D3DCUBEMAP_FACES FaceType, LONG lwMip, LONG lwSlice)
  1391. {
  1392.     HRESULT hr;
  1393.     CString fileName;
  1394.     LPDIRECT3DDEVICE8 pd3ddev = PDxtexApp()->Pd3ddev();
  1395.     LPDIRECT3DTEXTURE8 ptexOrig = NULL;
  1396.     LPDIRECT3DTEXTURE8 ptexNew = NULL;
  1397.     LPDIRECT3DSURFACE8 psurfOrig = NULL;
  1398.     LPDIRECT3DSURFACE8 psurfNew = NULL;
  1399.     LPDIRECT3DVOLUME8 pvolOrig = NULL;
  1400.     LPDIRECT3DVOLUME8 pvolNew = NULL;
  1401.     D3DSURFACE_DESC sd;
  1402.     DWORD dwWidth = m_dwWidth;
  1403.     DWORD dwHeight = m_dwHeight;
  1404.  
  1405.     if (IsVolumeMap())
  1406.     {
  1407.         for (int i = 0; i < lwMip; i++)
  1408.         {
  1409.             dwWidth /= 2;
  1410.             dwHeight /= 2;
  1411.         }
  1412.         hr = pd3ddev->CreateTexture(dwWidth, dwHeight, 1, 
  1413.              0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &ptexOrig);
  1414.         hr = ptexOrig->GetSurfaceLevel(0, &psurfOrig);
  1415.         hr = ((LPDIRECT3DVOLUMETEXTURE8)m_ptexOrig)->GetVolumeLevel(lwMip, &pvolOrig);
  1416.         hr = LoadSurfaceFromVolumeSlice(pvolOrig, lwSlice, psurfOrig);
  1417.         if (m_ptexNew != NULL)
  1418.         {
  1419.             hr = pd3ddev->CreateTexture(dwWidth, dwHeight, 1, 
  1420.                  0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &ptexNew);
  1421.             hr = ptexNew->GetSurfaceLevel(0, &psurfOrig);
  1422.             hr = ((LPDIRECT3DVOLUMETEXTURE8)m_ptexOrig)->GetVolumeLevel(lwMip, &pvolNew);
  1423.             hr = LoadSurfaceFromVolumeSlice(pvolNew, lwSlice, psurfOrig);
  1424.         }
  1425.     }
  1426.     else if (IsCubeMap())
  1427.     {
  1428.         hr = ((LPDIRECT3DCUBETEXTURE8)m_ptexOrig)->GetCubeMapSurface(FaceType, lwMip, &psurfOrig);
  1429.         ((LPDIRECT3DCUBETEXTURE8)m_ptexOrig)->GetLevelDesc(lwMip, &sd);
  1430.         if (sd.Format == D3DFMT_DXT2 || sd.Format == D3DFMT_DXT4)
  1431.         {
  1432.             AfxMessageBox(ID_ERROR_PREMULTALPHA);
  1433.             return;
  1434.         }
  1435.         if (m_ptexNew != NULL)
  1436.         {
  1437.             hr = ((LPDIRECT3DCUBETEXTURE8)m_ptexNew)->GetCubeMapSurface(FaceType, lwMip, &psurfNew);
  1438.             ((LPDIRECT3DCUBETEXTURE8)m_ptexNew)->GetLevelDesc(lwMip, &sd);
  1439.             if (sd.Format == D3DFMT_DXT2 || sd.Format == D3DFMT_DXT4)
  1440.             {
  1441.                 AfxMessageBox(ID_ERROR_PREMULTALPHA);
  1442.                 return;
  1443.             }
  1444.         }
  1445.     }
  1446.     else
  1447.     {
  1448.         hr = ((LPDIRECT3DTEXTURE8)m_ptexOrig)->GetSurfaceLevel(lwMip, &psurfOrig);
  1449.         ((LPDIRECT3DTEXTURE8)m_ptexOrig)->GetLevelDesc(lwMip, &sd);
  1450.         if (sd.Format == D3DFMT_DXT2 || sd.Format == D3DFMT_DXT4)
  1451.         {
  1452.             AfxMessageBox(ID_ERROR_PREMULTALPHA);
  1453.             return;
  1454.         }
  1455.         if (m_ptexNew != NULL)
  1456.         {
  1457.             hr = ((LPDIRECT3DTEXTURE8)m_ptexNew)->GetSurfaceLevel(lwMip, &psurfNew);
  1458.             ((LPDIRECT3DTEXTURE8)m_ptexNew)->GetLevelDesc(lwMip, &sd);
  1459.             if (sd.Format == D3DFMT_DXT2 || sd.Format == D3DFMT_DXT4)
  1460.             {
  1461.                 AfxMessageBox(ID_ERROR_PREMULTALPHA);
  1462.                 return;
  1463.             }
  1464.         }
  1465.     }
  1466.  
  1467.     if (!PromptForBmp(&fileName))
  1468.         return;
  1469.  
  1470.     if (FAILED(hr = LoadAlphaIntoSurface(fileName, psurfOrig)))
  1471.         return;
  1472.  
  1473.     if (psurfNew != NULL)
  1474.     {
  1475.         if (FAILED(hr = LoadAlphaIntoSurface(fileName, psurfNew)))
  1476.             return;
  1477.     }
  1478.  
  1479.     if (pvolOrig != NULL)
  1480.     {
  1481.         hr = LoadVolumeSliceFromSurface(pvolOrig, lwSlice, psurfOrig);
  1482.     }
  1483.     if (pvolNew != NULL)
  1484.     {
  1485.         hr = LoadVolumeSliceFromSurface(pvolNew, lwSlice, psurfNew);
  1486.     }
  1487.  
  1488.     ReleasePpo(&psurfOrig);
  1489.     ReleasePpo(&psurfNew);
  1490.     ReleasePpo(&ptexOrig);
  1491.     ReleasePpo(&ptexNew);
  1492.     ReleasePpo(&pvolOrig);
  1493.     ReleasePpo(&pvolNew);
  1494.  
  1495.     SetModifiedFlag(TRUE);
  1496.     UpdateAllViews(NULL, 1);
  1497. }
  1498.  
  1499.  
  1500. void CDxtexDoc::OnFormatChangeCubeMapFaces() 
  1501. {
  1502.     HRESULT hr;
  1503.     LPDIRECT3DDEVICE8 pd3ddev = PDxtexApp()->Pd3ddev();
  1504.     D3DSURFACE_DESC sd;
  1505.     LPDIRECT3DCUBETEXTURE8 ptexCube;
  1506.     DWORD iLevel;
  1507.     LPDIRECT3DSURFACE8 psurfSrc;
  1508.     LPDIRECT3DSURFACE8 psurfDest;
  1509.  
  1510.     CCubeMapDlg cubeMapDlg;
  1511.     if (IDCANCEL == cubeMapDlg.DoModal())
  1512.         return;
  1513.     
  1514.     // Change m_ptexOrig into a cubemap
  1515.     ((LPDIRECT3DTEXTURE8)m_ptexOrig)->GetLevelDesc(0, &sd);
  1516.     hr = D3DXCreateCubeTexture(pd3ddev, m_dwWidth, m_numMips, 0, sd.Format, D3DPOOL_MANAGED, &ptexCube);
  1517.     for (iLevel = 0; iLevel < m_numMips; iLevel++)
  1518.     {
  1519.         hr = ((LPDIRECT3DTEXTURE8)m_ptexOrig)->GetSurfaceLevel(iLevel, &psurfSrc);
  1520.         hr = ptexCube->GetCubeMapSurface((D3DCUBEMAP_FACES)cubeMapDlg.m_iFace, iLevel, &psurfDest);
  1521.         hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, 
  1522.             psurfSrc, NULL, NULL, D3DX_FILTER_TRIANGLE, 0);
  1523.         ReleasePpo(&psurfSrc);
  1524.         ReleasePpo(&psurfDest);
  1525.     }
  1526.     ReleasePpo(&m_ptexOrig);
  1527.     m_ptexOrig = ptexCube;
  1528.  
  1529.     // Change m_ptexNew into a cubemap too
  1530.     if (m_ptexNew != NULL)
  1531.     {
  1532.         ((LPDIRECT3DTEXTURE8)m_ptexNew)->GetLevelDesc(0, &sd);
  1533.         hr = D3DXCreateCubeTexture(pd3ddev, m_dwWidth, m_numMips, 0, sd.Format, D3DPOOL_MANAGED, &ptexCube);
  1534.         for (iLevel = 0; iLevel < m_numMips; iLevel++)
  1535.         {
  1536.             hr = ((LPDIRECT3DTEXTURE8)m_ptexNew)->GetSurfaceLevel(iLevel, &psurfSrc);
  1537.             hr = ptexCube->GetCubeMapSurface((D3DCUBEMAP_FACES)cubeMapDlg.m_iFace, iLevel, &psurfDest);
  1538.             hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, 
  1539.                 psurfSrc, NULL, NULL, D3DX_FILTER_TRIANGLE, 0);
  1540.             ReleasePpo(&psurfSrc);
  1541.             ReleasePpo(&psurfDest);
  1542.         }
  1543.         ReleasePpo(&m_ptexNew);
  1544.         m_ptexNew = ptexCube;
  1545.     }
  1546.     m_dwCubeMapFlags = DDS_CUBEMAP_ALLFACES;
  1547.     SetModifiedFlag();
  1548.     UpdateAllViews(NULL, 1); // tell CView to pick up new surface pointers
  1549. }
  1550.  
  1551.  
  1552. void CDxtexDoc::OnFormatMakeIntoVolumeMap() 
  1553. {
  1554.     HRESULT hr;
  1555.     LPDIRECT3DDEVICE8 pd3ddev = PDxtexApp()->Pd3ddev();
  1556.     D3DSURFACE_DESC sd;
  1557.     LPDIRECT3DVOLUMETEXTURE8 ptexVolume;
  1558.     DWORD iLevel;
  1559.     LPDIRECT3DSURFACE8 psurfSrc;
  1560.     LPDIRECT3DVOLUME8 pvolumeDest;
  1561.     UINT numLayers;
  1562.  
  1563.     CVolumeMapDlg volumeMapDlg;
  1564.     if (IDCANCEL == volumeMapDlg.DoModal())
  1565.         return;
  1566.  
  1567.     numLayers = (1 << volumeMapDlg.m_powLayers) * 2;
  1568.  
  1569.     // Change m_ptexOrig into a volumemap
  1570.     ((LPDIRECT3DTEXTURE8)m_ptexOrig)->GetLevelDesc(0, &sd);
  1571.     hr = pd3ddev->CreateVolumeTexture(m_dwWidth, m_dwHeight, numLayers,
  1572.         m_numMips, 0, sd.Format, D3DPOOL_SYSTEMMEM, &ptexVolume);
  1573.     if (FAILED(hr))
  1574.         return;
  1575.     for (iLevel = 0; iLevel < m_numMips; iLevel++)
  1576.     {
  1577.         hr = ((LPDIRECT3DTEXTURE8)m_ptexOrig)->GetSurfaceLevel(iLevel, &psurfSrc);
  1578.         hr = ptexVolume->GetVolumeLevel(iLevel, &pvolumeDest);
  1579.         hr = LoadVolumeSliceFromSurface(pvolumeDest, 0, psurfSrc);
  1580.         ReleasePpo(&psurfSrc);
  1581.         ReleasePpo(&pvolumeDest);
  1582.     }
  1583.     ReleasePpo(&m_ptexOrig);
  1584.     m_ptexOrig = ptexVolume;
  1585.  
  1586.     // Change m_ptexNew into a volumemap too
  1587.     if (m_ptexNew != NULL)
  1588.     {
  1589.         ((LPDIRECT3DTEXTURE8)m_ptexNew)->GetLevelDesc(0, &sd);
  1590.         hr = pd3ddev->CreateVolumeTexture(m_dwWidth, m_dwHeight, numLayers,
  1591.             m_numMips, 0, sd.Format, D3DPOOL_SYSTEMMEM, &ptexVolume);
  1592.         if (FAILED(hr))
  1593.             return;
  1594.         for (iLevel = 0; iLevel < m_numMips; iLevel++)
  1595.         {
  1596.             hr = ((LPDIRECT3DTEXTURE8)m_ptexNew)->GetSurfaceLevel(iLevel, &psurfSrc);
  1597.             hr = ptexVolume->GetVolumeLevel(iLevel, &pvolumeDest);
  1598.             hr = LoadVolumeSliceFromSurface(pvolumeDest, 0, psurfSrc);
  1599.             ReleasePpo(&psurfSrc);
  1600.             ReleasePpo(&pvolumeDest);
  1601.         }
  1602.         ReleasePpo(&m_ptexNew);
  1603.         m_ptexNew = ptexVolume;
  1604.     }
  1605.     m_dwDepth = numLayers;
  1606.     SetModifiedFlag();
  1607.     UpdateAllViews(NULL, 1); // tell CView to pick up new surface pointers
  1608. }
  1609.  
  1610.  
  1611. HRESULT CDxtexDoc::LoadVolumeSliceFromSurface(LPDIRECT3DVOLUME8 pVolume, UINT iSlice, LPDIRECT3DSURFACE8 psurf)
  1612. {
  1613.     HRESULT hr;
  1614.     D3DSURFACE_DESC sd;
  1615.     D3DVOLUME_DESC vd;
  1616.     D3DLOCKED_RECT lr;
  1617.     D3DBOX boxSrc;
  1618.     D3DBOX boxDest;
  1619.  
  1620.     psurf->GetDesc(&sd);
  1621.     pVolume->GetDesc(&vd);
  1622.  
  1623.     boxSrc.Left = 0;
  1624.     boxSrc.Right = sd.Width;
  1625.     boxSrc.Top = 0;
  1626.     boxSrc.Bottom = sd.Height;
  1627.     boxSrc.Front = 0;
  1628.     boxSrc.Back = 1;
  1629.  
  1630.     boxDest.Left = 0;
  1631.     boxDest.Right = vd.Width;
  1632.     boxDest.Top = 0;
  1633.     boxDest.Bottom = vd.Height;
  1634.     boxDest.Front = iSlice;
  1635.     boxDest.Back = iSlice + 1;
  1636.  
  1637.     hr = psurf->LockRect(&lr, NULL, 0);
  1638.     if (FAILED(hr))
  1639.         return hr;
  1640.  
  1641.     hr = D3DXLoadVolumeFromMemory(pVolume, NULL, &boxDest, lr.pBits, sd.Format, lr.Pitch, 
  1642.         0, NULL, &boxSrc, D3DX_FILTER_TRIANGLE, 0);
  1643.  
  1644.     psurf->UnlockRect();
  1645.  
  1646.     return hr;
  1647. }
  1648.  
  1649.  
  1650. HRESULT CDxtexDoc::LoadSurfaceFromVolumeSlice(LPDIRECT3DVOLUME8 pVolume, UINT iSlice, LPDIRECT3DSURFACE8 psurf)
  1651. {
  1652.     HRESULT hr;
  1653.     D3DVOLUME_DESC vd;
  1654.     D3DLOCKED_BOX lb;
  1655.     D3DBOX box;
  1656.     RECT rc;
  1657.  
  1658.     pVolume->GetDesc(&vd);
  1659.  
  1660.     box.Left = 0;
  1661.     box.Right = vd.Width;
  1662.     box.Top = 0;
  1663.     box.Bottom = vd.Height;
  1664.     box.Front = iSlice;
  1665.     box.Back = iSlice + 1;
  1666.  
  1667.     rc.left = 0;
  1668.     rc.right = vd.Width;
  1669.     rc.top = 0;
  1670.     rc.bottom = vd.Height;
  1671.  
  1672.     hr = pVolume->LockBox(&lb, &box, 0);
  1673.     if (FAILED(hr))
  1674.         return hr;
  1675.  
  1676.     hr = D3DXLoadSurfaceFromMemory(psurf, NULL, NULL, lb.pBits, vd.Format, lb.RowPitch, 
  1677.         NULL, &rc, D3DX_FILTER_TRIANGLE, 0);
  1678.  
  1679.     pVolume->UnlockBox();
  1680.  
  1681.     return hr;
  1682. }
  1683.  
  1684.  
  1685. HRESULT CDxtexDoc::BltAllLevels(D3DCUBEMAP_FACES FaceType, 
  1686.     LPDIRECT3DBASETEXTURE8 ptexSrc, LPDIRECT3DBASETEXTURE8 ptexDest)
  1687. {
  1688.     HRESULT hr;
  1689.     LPDIRECT3DTEXTURE8 pmiptexSrc;
  1690.     LPDIRECT3DTEXTURE8 pmiptexDest;
  1691.     LPDIRECT3DCUBETEXTURE8 pcubetexSrc;
  1692.     LPDIRECT3DCUBETEXTURE8 pcubetexDest;
  1693.     LPDIRECT3DVOLUMETEXTURE8 pvoltexSrc;
  1694.     LPDIRECT3DVOLUMETEXTURE8 pvoltexDest;
  1695.     LPDIRECT3DSURFACE8 psurfSrc;
  1696.     LPDIRECT3DSURFACE8 psurfDest;
  1697.     LPDIRECT3DVOLUME8 pvolSrc;
  1698.     LPDIRECT3DVOLUME8 pvolDest;
  1699.     DWORD iLevel;
  1700.  
  1701.     if (IsVolumeMap())
  1702.     {
  1703.         pvoltexSrc = (LPDIRECT3DVOLUMETEXTURE8)ptexSrc;
  1704.         pvoltexDest = (LPDIRECT3DVOLUMETEXTURE8)ptexDest;
  1705.     }
  1706.     else if (IsCubeMap())
  1707.     {
  1708.         pcubetexSrc = (LPDIRECT3DCUBETEXTURE8)ptexSrc;
  1709.         pcubetexDest = (LPDIRECT3DCUBETEXTURE8)ptexDest;
  1710.     }
  1711.     else
  1712.     {
  1713.         pmiptexSrc = (LPDIRECT3DTEXTURE8)ptexSrc;
  1714.         pmiptexDest = (LPDIRECT3DTEXTURE8)ptexDest;
  1715.     }
  1716.  
  1717.     for (iLevel = 0; iLevel < m_numMips; iLevel++)
  1718.     {
  1719.         if (IsVolumeMap())
  1720.         {
  1721.             hr = pvoltexSrc->GetVolumeLevel(iLevel, &pvolSrc);
  1722.             hr = pvoltexDest->GetVolumeLevel(iLevel, &pvolDest);
  1723.             hr = D3DXLoadVolumeFromVolume(pvolDest, NULL, NULL, 
  1724.                 pvolSrc, NULL, NULL, D3DX_FILTER_TRIANGLE, 0);
  1725.         }
  1726.         if (IsCubeMap())
  1727.         {
  1728.             hr = pcubetexSrc->GetCubeMapSurface(FaceType, iLevel, &psurfSrc);
  1729.             hr = pcubetexDest->GetCubeMapSurface(FaceType, iLevel, &psurfDest);
  1730.             hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, 
  1731.                 psurfSrc, NULL, NULL, D3DX_FILTER_TRIANGLE, 0);
  1732.         }
  1733.         else
  1734.         {
  1735.             hr = pmiptexSrc->GetSurfaceLevel(iLevel, &psurfSrc);
  1736.             hr = pmiptexDest->GetSurfaceLevel(iLevel, &psurfDest);
  1737.             hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, 
  1738.                 psurfSrc, NULL, NULL, D3DX_FILTER_TRIANGLE, 0);
  1739.         }
  1740.     }
  1741.  
  1742.     return S_OK;
  1743. }
  1744.  
  1745.  
  1746. void CDxtexDoc::OpenCubeFace(D3DCUBEMAP_FACES FaceType)
  1747. {
  1748.     HRESULT hr;
  1749.     CString fileName;
  1750.     LPDIRECT3DSURFACE8 psurfOrig = NULL;
  1751.     LPDIRECT3DSURFACE8 psurfNew = NULL;
  1752.  
  1753.     if (!IsCubeMap())
  1754.         return;
  1755.  
  1756.     hr = ((LPDIRECT3DCUBETEXTURE8)m_ptexOrig)->GetCubeMapSurface(FaceType, 0, &psurfOrig);
  1757.     if (m_ptexNew != NULL)
  1758.         hr = ((LPDIRECT3DCUBETEXTURE8)m_ptexNew)->GetCubeMapSurface(FaceType, 0, &psurfNew);
  1759.  
  1760.     if (!PromptForBmp(&fileName))
  1761.         return;
  1762.  
  1763.     hr = D3DXLoadSurfaceFromFile(psurfOrig, NULL, NULL, fileName, NULL, D3DX_FILTER_TRIANGLE, 0, NULL);
  1764.  
  1765.     // Look for "foo_a.bmp" for alpha channel
  1766.     int i = fileName.ReverseFind('.');
  1767.     fileName = fileName.Left(i) + "_a.bmp";
  1768.     CFileStatus status;
  1769.     if (CFile::GetStatus(fileName, status))
  1770.     {
  1771.         if (FAILED(hr = LoadAlphaIntoSurface(fileName, psurfOrig)))
  1772.             return;
  1773.     }
  1774.  
  1775.     if (m_numMips > 1)
  1776.     {
  1777.         hr = D3DXFilterCubeTexture((LPDIRECT3DCUBETEXTURE8)m_ptexOrig, NULL, 0, D3DX_FILTER_TRIANGLE);
  1778.     }
  1779.  
  1780.  
  1781.     if (psurfNew != NULL)
  1782.     {
  1783.         hr = D3DXLoadSurfaceFromSurface(psurfNew, NULL, NULL, psurfOrig, NULL, NULL, D3DX_FILTER_TRIANGLE, 0);
  1784.  
  1785.         if (m_numMips > 1)
  1786.         {
  1787.             hr = D3DXFilterCubeTexture((LPDIRECT3DCUBETEXTURE8)m_ptexNew, NULL, 0, D3DX_FILTER_TRIANGLE);
  1788.         }
  1789.     }
  1790.  
  1791.     ReleasePpo(&psurfOrig);
  1792.     ReleasePpo(&psurfNew);
  1793.  
  1794.     SetModifiedFlag(TRUE);
  1795.     UpdateAllViews(NULL, 1);
  1796. }
  1797.  
  1798.  
  1799. void CDxtexDoc::OpenAlphaCubeFace(D3DCUBEMAP_FACES FaceType)
  1800. {
  1801.     HRESULT hr;
  1802.     CString fileName;
  1803.     LPDIRECT3DSURFACE8 psurfOrig = NULL;
  1804.     LPDIRECT3DSURFACE8 psurfNew = NULL;
  1805.     D3DSURFACE_DESC sd;
  1806.  
  1807.     if (!IsCubeMap())
  1808.         return;
  1809.  
  1810.     hr = ((LPDIRECT3DCUBETEXTURE8)m_ptexOrig)->GetCubeMapSurface(FaceType, 0, &psurfOrig);
  1811.     ((LPDIRECT3DCUBETEXTURE8)m_ptexOrig)->GetLevelDesc(0, &sd);
  1812.     if (sd.Format == D3DFMT_DXT2 || sd.Format == D3DFMT_DXT4)
  1813.     {
  1814.         AfxMessageBox(ID_ERROR_PREMULTALPHA);
  1815.         return;
  1816.     }
  1817.     if (m_ptexNew != NULL)
  1818.     {
  1819.         hr = ((LPDIRECT3DCUBETEXTURE8)m_ptexNew)->GetCubeMapSurface(FaceType, 0, &psurfNew);
  1820.     }
  1821.  
  1822.     if (!PromptForBmp(&fileName))
  1823.         return;
  1824.  
  1825.     if (FAILED(hr = LoadAlphaIntoSurface(fileName, psurfOrig)))
  1826.         return;
  1827.  
  1828.     if (psurfNew != NULL)
  1829.     {
  1830.         if (FAILED(hr = LoadAlphaIntoSurface(fileName, psurfNew)))
  1831.             return;
  1832.     }
  1833.  
  1834.     if (m_numMips > 1)
  1835.     {
  1836.         hr = D3DXFilterCubeTexture((LPDIRECT3DCUBETEXTURE8)m_ptexOrig, NULL, 0, D3DX_FILTER_TRIANGLE);
  1837.     }
  1838.  
  1839.  
  1840.     if (psurfNew != NULL)
  1841.     {
  1842.         hr = D3DXLoadSurfaceFromSurface(psurfNew, NULL, NULL, psurfOrig, NULL, NULL, D3DX_FILTER_TRIANGLE, 0);
  1843.  
  1844.         if (m_numMips > 1)
  1845.         {
  1846.             hr = D3DXFilterCubeTexture((LPDIRECT3DCUBETEXTURE8)m_ptexNew, NULL, 0, D3DX_FILTER_TRIANGLE);
  1847.         }
  1848.     }
  1849.  
  1850.     ReleasePpo(&psurfOrig);
  1851.     ReleasePpo(&psurfNew);
  1852.  
  1853.     SetModifiedFlag(TRUE);
  1854.     UpdateAllViews(NULL, 1);
  1855. }
  1856.  
  1857.  
  1858. DWORD CDxtexDoc::DwDepthAt(LONG lwMip)
  1859. {
  1860.     DWORD dwDepth = m_dwDepth;
  1861.     while (lwMip > 0 && dwDepth > 1)
  1862.     {
  1863.         dwDepth /= 2;
  1864.         lwMip--;
  1865.     }
  1866.     return dwDepth;
  1867. }
  1868.  
  1869.  
  1870. void CDxtexDoc::OnFormatChangeSurfaceFmt() 
  1871. {
  1872.     CChangeFmtDlg changeFmtDlg;
  1873.     LPDIRECT3DBASETEXTURE8 ptex;
  1874.  
  1875.     ptex = (m_ptexNew == NULL ? m_ptexOrig : m_ptexNew);
  1876.  
  1877.     if (IsVolumeMap())
  1878.     {
  1879.         D3DVOLUME_DESC vd;
  1880.         ((LPDIRECT3DVOLUMETEXTURE8)ptex)->GetLevelDesc(0, &vd);
  1881.         changeFmtDlg.m_fmt = vd.Format;
  1882.     }
  1883.     else if (IsCubeMap())
  1884.     {
  1885.         D3DSURFACE_DESC sd;
  1886.         ((LPDIRECT3DCUBETEXTURE8)ptex)->GetLevelDesc(0, &sd);
  1887.         changeFmtDlg.m_fmt = sd.Format;
  1888.     }
  1889.     else
  1890.     {
  1891.         D3DSURFACE_DESC sd;
  1892.         ((LPDIRECT3DTEXTURE8)ptex)->GetLevelDesc(0, &sd);
  1893.         changeFmtDlg.m_fmt = sd.Format;
  1894.     }
  1895.  
  1896.     changeFmtDlg.m_bVolume = IsVolumeMap();
  1897.  
  1898.     if (IDCANCEL == changeFmtDlg.DoModal())
  1899.         return;
  1900.  
  1901.     Compress(changeFmtDlg.m_fmt, TRUE);
  1902. }
  1903.  
  1904.  
  1905. void CDxtexDoc::OnUpdateFileOpenAlpha(CCmdUI* pCmdUI) 
  1906. {
  1907.     pCmdUI->Enable(!IsCubeMap() && !IsVolumeMap()); 
  1908. }
  1909.  
  1910.  
  1911. void CDxtexDoc::OnUpdateFormatGenerateMipmaps(CCmdUI* pCmdUI) 
  1912. {
  1913.     pCmdUI->Enable(m_numMips <= 1); 
  1914. }
  1915.  
  1916.  
  1917. void CDxtexDoc::OnUpdateFormatChangeCubeMapFaces(CCmdUI* pCmdUI) 
  1918. {
  1919.     pCmdUI->Enable(!IsCubeMap() && !IsVolumeMap()); 
  1920. }
  1921.  
  1922.  
  1923. void CDxtexDoc::OnUpdateFormatMakeIntoVolumeMap(CCmdUI* pCmdUI) 
  1924. {
  1925.     pCmdUI->Enable(!IsCubeMap() && !IsVolumeMap());
  1926. }
  1927.  
  1928.  
  1929.